﻿using System;
using System.Reflection;
using System.Windows.Forms;

using Microsoft.Win32;
using System.Threading;
using System.IO;
using System.Diagnostics;


namespace SSH_Tunneling_GUI
{
    partial class frmMain : Form
    {
        private Boolean m_blnOnline = false; 
        private Process m_objProcess = null;
        private Boolean m_blnAbort = true;

        /// <summary>
        /// Set up dialog and menu and events
        /// </summary>
        public frmMain()
        {
            InitializeComponent();
            this.Text = String.Format("Info über {0}", AssemblyTitle);
            lblProductName.Text = AssemblyProduct;
            lblVersion.Text = String.Format("Version {0}", AssemblyVersion);
            lblCopyright.Text = AssemblyCopyright;
            lblCompanyName.Text = AssemblyCompany;
            txtDescription.Text = AssemblyDescription;

            nfiTray.Icon = Properties.Resources.ssh_off;
            tsmOffline.Enabled = false;
            tsmOnline.Enabled = true;

            tsmOffline.Text = Properties.Resources.MNU_OFFLINE;
            tsmOnline.Text = Properties.Resources.MNU_ONLINE;
            tsmOpen.Text = Properties.Resources.MNU_OPEN;
            tsmExit.Text = Properties.Resources.MNU_EXIT;

            lblProfile.Text = Properties.Resources.LBL_PROFILE;
            cmdOK.Text = Properties.Resources.CMD_OK;

            nfiTray.Text = Properties.Resources.TRAY_OFFLINE_TOOLTIP;

            cmdOK.Click += new EventHandler(cmdOK_Click);
            tsmExit.Click += new EventHandler(tsmExit_Click);
            tsmOffline.Click += new EventHandler(tsmOffline_Click);
            tsmOnline.Click += new EventHandler(tsmOnline_Click);
            tsmOpen.Click += new EventHandler(tsmOpen_Click);
            nfiTray.DoubleClick += new EventHandler(nfiTray_DoubleClick);

        }

        /// <summary>
        /// Toggles Menu, Icon and creates the backgroound plink process
        /// and keeps it alive until it receives the abort command 
        /// </summary>
        private void OpenTunnel()
        {
            if (txtProfile.Text == "")
            {
                MessageBox.Show(Properties.Resources.ERROR_NOPROFILE, ProductName);
                return;
            }

            Thread objThread = default(Thread);
            objThread = new Thread(CreateProcess);
            objThread.Start();
            m_blnOnline = true;
            nfiTray.Icon = Properties.Resources.ssh_on;
            nfiTray.Text = Properties.Resources.TRAY_ONLINE_TOOLTIP;
            tsmOffline.Enabled = true;
            tsmOnline.Enabled = false;
            m_blnAbort = false;
            while ((objThread.ThreadState != System.Threading.ThreadState.Stopped) & (m_blnAbort == false))
            {
                Application.DoEvents();
                Thread.Sleep(100);
            }
            if (m_blnAbort == true) m_objProcess.Kill();
            m_blnAbort = false;
            m_blnOnline = false;
            nfiTray.Icon = Properties.Resources.ssh_off;
            nfiTray.Text = Properties.Resources.TRAY_OFFLINE_TOOLTIP;
            tsmOffline.Enabled = false;
            tsmOnline.Enabled = true;
        }

        /// <summary>
        /// Abort process
        /// </summary>
        private void CloseTunnel()
        {
            m_blnAbort = true;
        }


        /// <summary>
        /// Creates the PLINK process
        /// </summary>
        private void CreateProcess()
        {
            string strCommand = null;
            string strParameter = null;
            StreamWriter objInputWriter = default(StreamWriter);
            StreamReader objOutputReader = default(StreamReader);
            StreamReader objErrorReader = default(StreamReader);
            var lngExitCode = 0;

            // plink.exe has to be located at the application directory
            strCommand = Application.StartupPath + "\\plink.exe";
            strParameter = " -N -load " + Properties.Settings.Default.Profile;

            ProcessStartInfo objProcessStartInfo = new ProcessStartInfo(strCommand, strParameter);
            objProcessStartInfo.UseShellExecute = false;
            objProcessStartInfo.ErrorDialog = false;
            objProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            objProcessStartInfo.CreateNoWindow = true;

            objProcessStartInfo.RedirectStandardError = true;
            objProcessStartInfo.RedirectStandardInput = true;
            objProcessStartInfo.RedirectStandardOutput = true;

            m_objProcess = new Process();
            m_objProcess.StartInfo = objProcessStartInfo;

            try
            {
                m_objProcess.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Properties.Resources.ERROR_PLINK);
                return;
            }

            objInputWriter = m_objProcess.StandardInput;
            objOutputReader = m_objProcess.StandardOutput;
            objErrorReader = m_objProcess.StandardError;

            m_objProcess.WaitForExit();
            lngExitCode = m_objProcess.ExitCode;
            m_objProcess.Close();
            m_objProcess = null;
        }

        #region "Eventhandling"
        /// <summary>
        /// DoubleClick toggles the tunnel online/offline
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void nfiTray_DoubleClick(object sender, EventArgs e)
        {
            if (m_blnOnline)
            {
                CloseTunnel();
            }
            else
            {
                OpenTunnel();
            }
        }

        /// <summary>
        /// Open main window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tsmOpen_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
            this.ShowInTaskbar = true;
            this.Show();
        }

        /// <summary>
        /// Close tunnel via menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tsmOnline_Click(object sender, EventArgs e)
        {
            OpenTunnel();
        }

        /// <summary>
        /// Close tunnel via menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tsmOffline_Click(object sender, EventArgs e)
        {
            CloseTunnel();
        }

        /// <summary>
        /// Kill plink process if running and exit application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tsmExit_Click(object sender, EventArgs e)
        {
            if (m_objProcess != null)
            {
                m_objProcess.Kill();
            }
            nfiTray.Visible = false;
            Application.Exit();
        }

        /// <summary>
        /// Save settings and hide window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cmdOK_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.Profile = txtProfile.Text;
            Properties.Settings.Default.Save();
            this.ShowInTaskbar = false;
            this.Hide();
        }
        #endregion

        #region Assemblyattributaccessoren

        public string AssemblyTitle
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
                if (attributes.Length > 0)
                {
                    AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
                    if (titleAttribute.Title != "")
                    {
                        return titleAttribute.Title;
                    }
                }
                return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
            }
        }

        public string AssemblyVersion
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }
        }

        public string AssemblyDescription
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyDescriptionAttribute)attributes[0]).Description;
            }
        }

        public string AssemblyProduct
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyProductAttribute)attributes[0]).Product;
            }
        }

        public string AssemblyCopyright
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
            }
        }

        public string AssemblyCompany
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyCompanyAttribute)attributes[0]).Company;
            }
        }
        #endregion


    }
}
